package com.spring.demo.untils.document.nio;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

/**
 * @author xuweizhi
 * @since 2023/04/26 10:07
 */
public class NioUtil {

    private static void byteBuffer() throws IOException {
        RandomAccessFile randomAccessFile = new RandomAccessFile("/Users/zhengwei/lanqiao/ConditionOperator.java", "rw");
        FileChannel channel = randomAccessFile.getChannel();
        ByteBuffer buffer = ByteBuffer.allocate(10);
        int bytesRead = channel.read(buffer);
        while (bytesRead != -1) {
            // System.out.println("读取字节数："+bytesRead);
            // 之前是写buffer，现在要读buffer
            buffer.flip();// 切换模式，写->读
            // 这样读取，如果10字节恰好分割了一个字符将出现乱码
            System.out.print(StandardCharsets.UTF_8.decode(buffer));
            buffer.clear();// 清空,position位置为0，limit=capacity
            // 继续往buffer中写
            bytesRead = channel.read(buffer);
        }
        randomAccessFile.close();
    }

    public static <R> List<R> readLine(String filePath, Function<String, R> consumer) {
        List<R> objects = new ArrayList<>();
        RandomAccessFile randomAccessFile = null;
        try {

            randomAccessFile = new RandomAccessFile(filePath, "rw");
            FileChannel channel = randomAccessFile.getChannel();
            ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024);
            int bytesRead = channel.read(buffer);
            ByteBuffer stringBuffer = ByteBuffer.allocate(64);
            while (bytesRead != -1) {
                System.out.println("读取字节数：" + bytesRead);
                //之前是写buffer，现在要读buffer
                buffer.flip();// 切换模式，写->读
                while (buffer.hasRemaining()) {
                    byte b = buffer.get();
                    // 换行或回车
                    if (b == 10 || b == 13) {
                        stringBuffer.flip();
                        // 这里就是一个行
                        final String line = StandardCharsets.UTF_8.decode(stringBuffer).toString();
                        objects.add(consumer.apply(line));
                        // 解码已经读到的一行所对应的字节
                        // System.out.println(line);
                        stringBuffer.clear();
                    } else {
                        if (stringBuffer.hasRemaining()) {
                            stringBuffer.put(b);
                        } else { // 空间不够扩容
                            stringBuffer = reAllocate(stringBuffer);
                            stringBuffer.put(b);
                        }
                    }
                }
                // 清空,position位置为0，limit=capacity
                buffer.clear();
                //  继续往buffer中写
                bytesRead = channel.read(buffer);
            }
            randomAccessFile.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (randomAccessFile != null) {
                try {
                    randomAccessFile.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return objects;
    }

    private static ByteBuffer reAllocate(ByteBuffer stringBuffer) {
        final int capacity = stringBuffer.capacity();
        byte[] newBuffer = new byte[capacity * 2];
        System.arraycopy(stringBuffer.array(), 0, newBuffer, 0, capacity);
        return ByteBuffer.wrap(newBuffer).position(capacity);
    }


}
